<template>
  <a-table :columns="columns" :data-source="dataSource" bordered> </a-table>
</template>
<script setup>

/* 
代码中使用的三个主要函数是countFieldDuplicates，mergeCell和convertData。

countFieldDuplicates：该函数接受两个参数，数据数组和要统计重复次数的字段。该函数返回一个包含每个值重复次数的对象。
mergeCell：该函数接受一个数组，其中包含表格的列信息。该函数返回一个新的包含更新列信息的数组，其中更新的列信息具有一个自定义单元格渲染器，该渲染器在某些列中设置rowSpan属性。
convertData：该函数接受一个数组，其中包含表格数据。该函数将数据转换为新数组，其中包含每个单元格的rowSpan属性。
在该组件中，常量rule是一个对象，其中包含每个要设置rowSpan属性的列的名称和值“rowSpan”。

接下来，使用mergeCell函数，将包含表格列的数组传递给它，并将返回的数组保存在常量columns中。然后，通过过滤departmentList列并将结果映射到dataIndex数组来设置colKeys常量。

最后，使用convertData函数将包含表格数据的数组传递给它，将返回新数组dataSource，其中包含每个单元格的rowSpan属性，以便在渲染表格时使用。

*/

// 定义一个规则对象，包含四个属性，每个属性对应一个表格列
// 用于表示在表格中这些列应该被合并成一个单元格
const rule = {
  classification: "rowSpan",
  project: "rowSpan",
  info: "rowSpan",
  content: "rowSpan",
  departmentList: 'rowSpan'
}

// 统计给定数据中某一列的重复值的数量
const countFieldDuplicates = (data, field) => {
  // 用于存储列中所有值的数组
  var values = [];
  // 用于存储每个值出现的次数的对象
  var counts = {};

  // 遍历数据中的每一行
  for (var i = 0; i < data.length; i++) {
    // 获取当前行在指定列上的值
    var value = data[i][field];
    // 将当前值加入 values 数组中
    values.push(value);

    // 如果当前值已经在 counts 对象中存在，说明这个值是重复的
    // 那么将对应的计数器加 1
    // 否则，创建一个新的计数器，将其值设置为 1
    if (counts[value]) {
      counts[value]++;
    } else {
      counts[value] = 1;
    }
  }

  // 返回计数器对象
  return counts;
};

// 用于将表格中需要合并单元格的列转换为合并规则的函数
const mergeCell = (cols) => {
  // 遍历每一列
  return cols.map((item) => {
    return {
      // 将原列对象的属性全部复制到新列对象中
      ...item,
      // 自定义单元格渲染函数
      customCell: (record, index, currentCol) => {
        // 如果当前列存在
        if (currentCol) {
          // 获取当前行在当前列上的合并单元格数量
          const mergeNum = (record)[`${currentCol.dataIndex}Merge`];
          // 如果当前列需要被合并单元格
          if (colKeys.includes((currentCol).dataIndex)) {
            // 获取当前列应该合并的目标单元格的标识符
            const mergeCellKey = rule[(currentCol).dataIndex];
            // 创建一个包含目标单元格标识符和合并单元格数量的对象
            const mergeInfo = {};
            mergeInfo[mergeCellKey] = mergeNum || 0;
            // 返回合并信息对象
            return mergeInfo
          }
        }
      },
    };
  });
};

// 定义表格的列信息
const columns = mergeCell([
  {
    key: "1",
    title: "类别",
    dataIndex: "classification"
  },
  {
    key: "2",
    title: "项目评价",
    dataIndex: "project",
  },
  {
    key: "3",
    title: "评价内容",
    dataIndex: "info",
  },
  {
    key: "4",
    title: "项目评价点",
    dataIndex: "content",
  },
  {
    key: "5",
    title: "评价部门",
    dataIndex: "departmentList",
    // customRender: ({ text }) => {
    //   return text.map((item) => item.deptName);
    // },
  },
]);

// 过滤掉 columns 中 dataIndex 为 "departmentList" 的项，然后将剩下的项的 dataIndex 组成一个数组 colKeys
const colKeys = columns
  // .filter((item) => item.dataIndex !== "departmentList")
  .map((item) => item.dataIndex);

// 定义一个转换数据的函数 convertData，传入一个数据数组 data
const convertData = (data) => {
  // 复制一份数据数组并存入 currentData 变量
  const currentData = [...data];
  // 对于 colKeys 数组中的每一个 dataIndex，找出所有相同字段值的项并进行处理
  colKeys.forEach((colKey) => {
    // 找出 currentData 数组中，每个 dataIndex 等于 colKey 的项的个数
    const fieldDuplicates = countFieldDuplicates(currentData, colKey);
    // 找出 fieldDuplicates 对象中的所有属性（即相同字段值），并对于每一个属性执行以下操作
    const duplicateKeys = Object.keys(fieldDuplicates);
    duplicateKeys.forEach((duplicateKey) => {
      // 找出 currentData 数组中，第一个 dataIndex 等于 colKey 并且值等于 duplicateKey 的项的下标 idx
      const idx = currentData.findIndex(
        (item) => item[colKey] === duplicateKey
      );
      // 对于 currentData 数组中下标大于 idx 且小于相同字段值个数的项，在该项中加入一个 `${colKey}Merge` 字段
      for (let i = 0; i < currentData.length; i++) {
        if (i === idx) {
          (currentData[i])[`${colKey}Merge`] =
            fieldDuplicates[duplicateKey];
        }
        if (i > idx && i < fieldDuplicates[duplicateKey]) {
          (currentData[i])[`${colKey}Merge`] = 0;
        }
      }
    });
  });
  // 返回处理后的数据数组 currentData
  return currentData;
};

// 调用 convertData 函数，传入一个数据数组作为参数，并将返回结果赋给 dataSource 变量
const dataSource = convertData([
  {
    classification: "安全管理（200分）",
    // classificationMerge
    project: "安全生产责任制",
    info: "结合实际制定总体和年度安全生产和职业卫生目标,明确制定、分解、实施、检查、考核等环节要求，确保落实。 严格执行安全生产委员会工作制度。",
    id: 4,
    content:
      "年度安全生产和职业卫生目标制定、分解、实施、检查、考核各环节要求未落实，每项减1分。",
    type: 3,
    pid: 3,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "安全管理（200分）",
    project: "安全生产责任制",
    info: "结合实际制定总体和年度安全生产和职业卫生目标,明确制定、分解、实施、检查、考核等环节要求，确保落实。 严格执行安全生产委员会工作制度。",
    id: 5,
    content:
      "安全生产责任制不健全，缺一个岗位减2分；公示、教育培训、考核等要求不健全、不落实，每项减1分。",
    type: 3,
    pid: 3,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "安全管理（200分）",
    project: "安全生产责任制",
    info: "建立健全全员岗位责任制，明确履职清单，严格履职过程考评，考评结果要与职务晋升、奖励惩处挂钩。严格落实党政同责、一岗双责、失职追责，段长严格安全生产管理职责履职。安全管理制度健全。",
    id: 7,
    content:
      "未建立履职清单，缺一个岗位减2分；未按履职清单进行过程考核和质量考评，减3分；考评结果未与职务晋升、奖励惩处挂钩，减2分；抽查5名干部履职情况（含站段长）月度安全职责履职及考评情况，发现问题每个减2分。",
    type: 3,
    pid: 6,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "安全管理（200分）",
    project: "安全生产责任制",
    info: "建立健全全员岗位责任制，明确履职清单，严格履职过程考评，考评结果要与职务晋升、奖励惩处挂钩。严格落实党政同责、一岗双责、失职追责，段长严格安全生产管理职责履职。安全管理制度健全。",
    id: 8,
    content:
      "事故失职责任追究办法未建立，减3分；办法不符合“管生产经营必须管安全、管业务必须管安全”原则，办法不健全，每项减2分；发生事故未按办法规定追究责任，每人次减1分。",
    type: 3,
    pid: 6,
    departmentList: "法律部|行政管理部|工程部0"
  },
  {
    classification: "安全管理（200分）",
    project: "安全生产责任制",
    info: "建立健全全员岗位责任制，明确履职清单，严格履职过程考评，考评结果要与职务晋升、奖励惩处挂钩。严格落实党政同责、一岗双责、失职追责，段长严格安全生产管理职责履职。安全管理制度健全。",
    id: 9,
    content:
      "安全管理制度不健全，每项减2分，修订不及时、落实不到位、未及时清理以及内容与上级规章冲突的，每处减1分。",
    type: 3,
    pid: 6,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "服务质量(100分)",
    project: "客服设施",
    info: "客运服务设备设施配置齐全、作用良好。基础设施设备符合设计规范，定期维护，作用良好，无违规改造和改变用途。站内标识规范、揭示揭挂齐全。旅服系统运行稳定可靠，自动检票、导向、广播、时钟、查询、求助等旅客服务设备设施齐全，状态良好。售票设施设备满足生产需要，作用良好。",
    id: 13,
    content:
      "客运服务设备设施未按规定配置的，缺少一处，减2分。作用良好率日常90%及以上，春暑运、小长假期间95%以上，期间检查不达标的，一次减5分。",
    type: 3,
    pid: 12,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "服务质量(100分)",
    project: "客服设施",
    info: "客运服务设备设施配置齐全、作用良好。基础设施设备符合设计规范，定期维护，作用良好，无违规改造和改变用途。站内标识规范、揭示揭挂齐全。旅服系统运行稳定可靠，自动检票、导向、广播、时钟、查询、求助等旅客服务设备设施齐全，状态良好。售票设施设备满足生产需要，作用良好。",
    id: 14,
    content: "发生客服系统I类故障，每起减5分，发生Ⅱ类故障的，每起减2分。",
    type: 3,
    pid: 12,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "服务质量(100分)",
    project: "客服设施",
    info: "客运服务设备设施配置齐全、作用良好。基础设施设备符合设计规范，定期维护，作用良好，无违规改造和改变用途。站内标识规范、揭示揭挂齐全。旅服系统运行稳定可靠，自动检票、导向、广播、时钟、查询、求助等旅客服务设备设施齐全，状态良好。售票设施设备满足生产需要，作用良好。",
    id: 15,
    content: "基础设施设备违规改造和改变用途的，每起减3分。",
    type: 3,
    pid: 12,
    departmentList: "法律部|行政管理部|工程部"
  },
  {
    classification: "服务质量(100分)",
    project: "客服设施",
    info: "客运服务设备设施配置齐全、作用良好。基础设施设备符合设计规范，定期维护，作用良好，无违规改造和改变用途。站内标识规范、揭示揭挂齐全。旅服系统运行稳定可靠，自动检票、导向、广播、时钟、查询、求助等旅客服务设备设施齐全，状态良好。售票设施设备满足生产需要，作用良好。",
    id: 16,
    content:
      "车站标识、揭示揭挂缺失的，每处减2分；标识不规范、不统一、不准确、不连续等问题，每处减1分。",
    type: 3,
    pid: 12,
    departmentList: "法律部|行政管理部|工程部"
  },
]);

// const obj = {
//   v1: {
//     x: 100,
//     value: {
//       z: 200
//     }
//   },
//   v2: {
//     x: 1001,
//     value: {
//       z: 2000
//     }
//   },
//   v3: {
//     x: 100,
//     value: {
//       z: 200
//     }
//   },
//   v4: {
//     x: 100,
//     value: {
//       z: 200
//     }
//   },
// }

// const keys = Object.keys(obj)
// const result = keys.reduce((o, key) => {
//   o.push({
//     x: obj[key].x,
//     z: obj[key].value.z
//   })
//   return o
// }, [])

// console.log(result)

// const obj = {}
// const x = 'aaa'
// obj[`${x}Merge`] = 'abc'
// console.log(obj)
</script>
